package com.yx.framedemo.model.utils.request;


import android.util.Log;

import com.yx.framedemo.model.a.DemoModelBean;
import com.yx.framedemo.model.utils.net.RetrofitUtils;
import com.yx.framedemo.model.utils.net.RxException;
import com.yx.framedemo.model.utils.net.RxSchedulers;
import com.yx.framedemo.model.utils.result.DataCallback;
import com.yx.framedemo.model.utils.result.HttpNoResult;
import com.yx.framedemo.model.utils.result.HttpResult;
import com.yx.framedemo.view.utils.toast.ToastUtils;

import io.reactivex.Observer;
import io.reactivex.annotations.NonNull;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import okhttp3.RequestBody;

/**
 * 所有接口实现，一一对应所定义的接口
 * Rx写法 + Retrofit
 *
 * @author _Yx
 * Created by os on 2018/8/8.
 * ※ .execute同步请求，需等上一个线程执行完才执行下一个
 * ※ .enqueue异步请求，多个请求通过CPU循环调用，抢占CPU
 * ※ new Consumer()与new Observer（）区别：
 * Consumer是简易版的Observer他有多重重载，可以自定义你需要处理的信息，我这里调用的是只接受onNext消息的方法，
 * 他只提供一个回调接口accept，由于没有onError和onCompete，无法再 接受到onError或者onCompete之后，实现函数回调。
 * 无法回调，并不代表不接收，他还是会接收到onCompete和onError之后做出默认操作，也就是监听者（Consumer）不在接收
 * Observable发送的消息。
 * 简易版写法：https: //  www.it610.com/article/1280209006605910016.htm
 * ※ 关于提示：The result of subscribe is not used问题
 * 参考：https: //  blog.csdn.net/cysion1989/article/details/84501399
 * 因为AS并不知道这个没有使用（分解）的订阅会有什么潜在的风险，
 * 例如：若在事件流中有耗时操作，同时事件流中某个事件又持有了Activity的引用，
 * 那么当Activity被关闭时，其引用仍会被未结束的事件所持有，会造成内存泄露
 * 解决方式很简单，就是在subscribe时将这个Disposable对象赋值给一个变量可以去掉lint提示了，
 * 因为这时候IDE会认为你将会对这个变量有其它操作,仍然存风险，因为赋值后不处理嘛,风险还是存在。
 * 那么使用CompositeDisposable类来管理每一个注册事件流，等不需要的时候，将disposable对象dispose掉。
 * 需要注意的是，只有在调用Observable的subscribe方法时，网络请求才会触发，订阅即触发
 * dispose():主动解除订阅
 * isDisposed():查询是否解除订阅 true 代表 已经解除订阅
 */
public class ModelApiImpl { //  所有接口方法实现在这里↓

    //  ---------订阅操作👇-----------
    private CompositeDisposable co = new CompositeDisposable(); //  订阅管理器，Disposable指某个订阅对象

    private void addDisposable(Disposable d) { //  添加订阅对象
        if (co != null && !co.isDisposed()) {
            co.add(d);
        }
    }

    public void clearDisposable() { //  清空订阅对象，则当前订阅的所有网络请求立马中断
        if (co != null) {
            co.clear();  //   clear时网络请求会随即cancel
            co = null;
        }
    }
    //  ---------订阅↑-----------

    /**
     * 正常方法
     * 获取Demo信息Info
     * <p>
     * 下面的都改成Lambda写法了
     *
     * @param tokenkey
     * @param requestBody
     */
    public void getDemoInfo(final String tokenkey, final RequestBody requestBody, DataCallback<DemoModelBean> dataCallback) {
        Disposable d = RetrofitUtils.getInstance().apiService
                .getDemoInfos(tokenkey, requestBody)
                .compose(RxSchedulers.io_mains())
                .subscribe(new Consumer<HttpResult<DemoModelBean>>() {
                    @Override
                    public void accept(@NonNull HttpResult<DemoModelBean> mResult) throws Exception {
                        dataCallback.onSuccess(mResult.getData());
                    }
                }, new RxException<>(new Consumer<Throwable>() {
                    @Override
                    public void accept(Throwable throwable) throws Exception {
                        ToastUtils.showToastApplication("请求失败");
                        throwable.printStackTrace();
                    }
                }));

        addDisposable(d);

    }

    /**
     * Lambda 方式
     * 获取Demo的Info
     *
     * @param tokenkey
     * @param requestBody
     */
    public void getDemoInfoLambda(final String tokenkey, final RequestBody requestBody, DataCallback<DemoModelBean> dataCallback) {
        RetrofitUtils.getInstance().apiService
                .getDemoInfos(tokenkey, requestBody)
                .compose(RxSchedulers.io_mains())
                .subscribe(mResult -> {
                            if (mResult != null && "1".equals(mResult.getStatus()) && mResult.getData() != null) {
                                if (dataCallback != null) {
                                    dataCallback.onSuccess(mResult.getData());
                                }
                            }
                        },
                        new RxException<>(throwable -> Log.i("aaaa", throwable.getMessage())));
    }


    /**
     * Lambda 方式
     * 获取Demo的Users
     *
     * @param tokenkey
     * @param requestBody
     */
    public void getDemoUsers(final String tokenkey, final RequestBody requestBody, DataCallback<String> dataCallback) {
        Disposable d = RetrofitUtils.getInstance().apiService
                .getDemoUsers(tokenkey, requestBody)
                .compose(RxSchedulers.io_mains())
                .subscribe(mResult -> {
                            if (mResult != null && "1".equals(mResult.getStatus())) {
                                if (dataCallback != null) {
                                    dataCallback.onSuccess(mResult.getMsg());
                                }
                            }
                        },
                        new RxException<>(throwable -> Log.i("aaaa", throwable.toString())));
        addDisposable(d);
    }

    /**
     * new Consumer()与new Observer（）区别详解（类上有详解）
     */
    public void getDemoTips(final String tokenkey, final RequestBody requestBody, DataCallback<String> dataCallback) {
        RetrofitUtils.getInstance().apiService
                .getDemoUsers(tokenkey, requestBody)
                .compose(RxSchedulers.io_mains()).subscribe(new Observer<HttpNoResult>() {
            //  四个方法逻辑过程：https: //  www.it610.com/article/1280350890678566912.htm
            @Override
            public void onSubscribe(Disposable d) {
                //  1.每次接收数据之前必须要调用的方法；

            }

            @Override
            public void onNext(HttpNoResult httpNoResult) {
                //  2.相当于传统观察者模式中得update(),
                //   当被观察者发生状态改变时 ；观察者的处理对应业务逻辑

            }

            @Override
            public void onError(Throwable e) {
                //  S。处理异常时，框架的回调

            }

            @Override
            public void onComplete() {
                //  3.当不在有被观察者发生状态改变时，观察者在这处里终极逻辑

            }
        });
    }


}
